<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="80px">
      <el-form-item label="所属项目" prop="projectId">
        <el-select clearable @change="handleQuery" v-model="queryParams.projectId" placeholder="请选择项目">
          <el-option v-for="item in projectOptions" :key="item.id" :label="item.projectName" :value="item.id" />
        </el-select>
      </el-form-item>

      <el-form-item label="施工日期" prop="constructionDate">
        <el-date-picker v-model="queryParams.constructionDate" type="date" value-format="yyyy-MM-dd"
          placeholder="请选择施工日期" clearable @change="handleQuery" style="width: 190px">
        </el-date-picker>
      </el-form-item>

      <!-- <el-form-item label="充盈系数" prop="fillingCoefficient">
        <el-input v-model="queryParams.fillingCoefficient" placeholder="请输入充盈系数" clearable
          @keyup.enter.native="handleQuery" />
      </el-form-item> -->

      <!-- <el-form-item label="安全情况" prop="safetyStatus">
        <el-select clearable @change="handleQuery" v-model="queryParams.safetyStatus" placeholder="请选择安全情况" filterable>
          <el-option v-for="dict in dict.type.safety_status" :key="dict.value" :label="dict.label"
            :value="dict.value" />
        </el-select>
      </el-form-item> -->

      <!-- 
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item> -->
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd"
          v-hasPermi="['production:projectDailyReport:add']">新增</el-button>
      </el-col>
      <!-- <el-col :span="1.5">
        <el-button type="success" icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate"
          v-hasPermi="['production:projectDailyReport:edit']">修改</el-button>
      </el-col> -->
      <el-col :span="1.5">
        <el-button type="danger" icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
          v-hasPermi="['production:projectDailyReport:remove']">删除</el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button type="warning" icon="el-icon-download" size="mini" @click="handleExport"
          v-hasPermi="['production:projectDailyReport:export']">导出</el-button>
      </el-col>
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>

    <el-table v-loading="loading" :data="projectDailyReportList" @selection-change="handleSelectionChange">
      <el-table-column type="selection" width="55" align="center" />
      <el-table-column label="名称" align="center" prop="constructionDate">
        <template slot-scope="scope">
          {{ getDateOnly(scope.row.constructionDate) + '日施工日志' }}
        </template>
      </el-table-column>
      <el-table-column label="填报时间" align="center" prop="createTime" width="180">
        <template slot-scope="scope">
          {{ changeTime(scope.row.createTime) }}
        </template>
      </el-table-column>
      <el-table-column label="填报人" align="center" prop="createBy" />
      <el-table-column label="所属项目" align="center" prop="projectId" width="170">
        <template slot-scope="scope">
          <el-tooltip class="item" effect="dark" :content="getProjectNameById(scope.row.projectId)" placement="top">
            <span
              style="max-width: 120px; display: inline-block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle;"
              :title="getProjectNameById(scope.row.projectId)">
              {{ getProjectNameById(scope.row.projectId) }}
            </span>
          </el-tooltip>
        </template>
      </el-table-column>
      <el-table-column label="工程桩数（根）" width="120" align="center" prop="usePower">
        <template slot-scope="scope">
          {{ scope.row.pileCount }}
        </template>
      </el-table-column>
      <el-table-column label="安全情况" width="120" align="center" prop="safetyStatus">
        <template slot-scope="scope">
          <dict-tag :options="dict.type.safety_status" :value="scope.row.safetyStatus" />
        </template>
      </el-table-column>
      <el-table-column label="设备情况" width="120" align="center" prop="equipmentStatus">
        <template slot-scope="scope">
          <dict-tag :options="dict.type.facility_status" :value="scope.row.equipmentStatus" />
        </template>
      </el-table-column>
      <!-- <el-table-column label="天气" align="center" prop="weather" />
      <el-table-column label="管理人员数量" align="center" prop="managerCount" />
      <el-table-column label="班组人员数量" align="center" prop="workerCount" />
      <el-table-column label="施工工程量" align="center" prop="workAmount" />
      <el-table-column label="充盈系数" align="center" prop="fillingCoefficient" />
      <el-table-column label="其他补充说明" align="center" prop="otherSupplement" />
      <el-table-column label="安全情况" align="center" prop="safetyStatus">
        <template slot-scope="scope">
          <dict-tag :options="dict.type.safety_status" :value="scope.row.safetyStatus" />
        </template>
      </el-table-column>
      <el-table-column label="安全异常情况说明" align="center" prop="safetyRemark" />
      <el-table-column label="设备情况" align="center" prop="equipmentStatus">
        <template slot-scope="scope">
          <dict-tag :options="dict.type.facility_status" :value="scope.row.equipmentStatus" />
        </template>
      </el-table-column>
      <el-table-column label="设备情况说明" align="center" prop="equipmentRemark" />
      <el-table-column label="次日计划" align="center" prop="nextDayPlan" /> -->
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
            v-hasPermi="['production:projectDailyReport:edit']">修改</el-button>
          <el-button size="mini" type="text" icon="el-icon-view" @click="handleDetail(scope.row)">详情</el-button>
          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
            v-hasPermi="['production:projectDailyReport:remove']">删除</el-button>

        </template>
      </el-table-column>
    </el-table>

    <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
      @pagination="getList" />

    <!-- 添加或修改项目日志对话框 -->
    <el-dialog :title="title" :visible.sync="open" width="750px" append-to-body>
      <el-form ref="form" :model="form" :inline="true" :rules="rules" label-width="140px">
        <el-form-item label="选择项目" prop="projectId">
          <el-select v-model="form.projectId" placeholder="请选择项目" style="width:190px">
            <el-option v-for="item in projectOptions" :key="item.id" :label="item.projectName" :value="item.id" />
          </el-select>
        </el-form-item>
        <el-form-item label="施工日期" prop="constructionDate">
          <el-date-picker style="width:190px" clearable v-model="form.constructionDate" type="date"
            value-format="yyyy-MM-dd HH:mm:ss" placeholder="请选择施工日期">
          </el-date-picker>
        </el-form-item>
        <el-form-item label="天气" prop="weather">
          <el-input v-model="form.weather" placeholder="请输入天气" />
        </el-form-item>
        <el-form-item label="管理人员数量" prop="managerCount">
          <el-input v-model="form.managerCount" placeholder="请输入管理人员数量" @input="validatePositiveInteger('managerCount')"
            @blur="formatPositiveInteger('managerCount')" />
        </el-form-item>
        <el-form-item label="班组人员数量" prop="workerCount">
          <el-input v-model="form.workerCount" placeholder="请输入班组人员数量" @input="validatePositiveInteger('workerCount')"
            @blur="formatPositiveInteger('workerCount')" />
        </el-form-item>
        <el-form-item label="桩基设备型号" prop="pileEquipmentModel">
          <el-input v-model="form.pileEquipmentModel" placeholder="请输入桩基设备型号" />
        </el-form-item>
        <el-form-item label="桩基设备数量" prop="pileEquipmentCount">
          <el-input v-model="form.pileEquipmentCount" placeholder="请输入桩基设备数量"
            @input="validatePositiveInteger('pileEquipmentCount')"
            @blur="formatPositiveInteger('pileEquipmentCount')" />
        </el-form-item>
        <el-form-item label="工程桩数（根）" prop="pileCount">
          <el-input v-model="form.pileCount" placeholder="请输入工程桩数" @input="validatePositiveInteger('pileCount')"
            @blur="formatPositiveInteger('pileCount')" />
        </el-form-item>
        <el-form-item label="工程量（米）" prop="workLength">
          <el-input v-model="form.workLength" placeholder="请输入工程量" @input="validateWorkLength"
            @blur="formatWorkLength" />
        </el-form-item>
        <!-- <el-form-item label="施工工程量" prop="workAmount">
          <el-input v-model="form.workAmount" placeholder="请输入施工工程量" />
        </el-form-item> -->
        <el-form-item label="充盈系数" prop="fillingCoefficient">
          <el-input v-model="form.fillingCoefficient" placeholder="请输入充盈系数"
            @input="validatePositiveNumber('fillingCoefficient')" @blur="formatPositiveNumber('fillingCoefficient')" />
        </el-form-item>
        <el-form-item label="用电量" prop="usePower">
          <el-input v-model="form.usePower" placeholder="请输入用电量" @input="validatePositiveNumber('usePower')"
            @blur="formatPositiveNumber('usePower')" />
        </el-form-item>
        <el-form-item label="用油量" prop="oilConsumption">
          <el-input v-model="form.oilConsumption" placeholder="请输入用油量" @input="validatePositiveNumber('oilConsumption')"
            @blur="formatPositiveNumber('oilConsumption')" />
        </el-form-item>
        <el-form-item label="停工时间" prop="downtime">
          <el-input v-model="form.downtime" placeholder="请输入停工时间" />
        </el-form-item>
        <el-form-item label="其他补充说明" prop="otherSupplement">
          <el-input v-model="form.otherSupplement" style="width:560px" type="textarea" placeholder="请输入内容" />
        </el-form-item>
        <el-form-item label="安全情况" prop="safetyStatus">
          <el-radio-group v-model="form.safetyStatus">
            <el-radio v-for="dict in dict.type.safety_status" :key="dict.value" :label="dict.value">{{
              dict.label
            }}</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item v-if="form.safetyStatus != 1" label="安全异常情况说明" prop="safetyRemark" style="margin-left: 28px;">
          <el-input v-model="form.safetyRemark" type="textarea" style="width:190px" placeholder="请输入安全异常情况说明" />
        </el-form-item>
        <el-form-item label="设备情况" prop="equipmentStatus">
          <el-radio-group v-model="form.equipmentStatus">
            <!-- parseInt -->
            <el-radio v-for="dict in dict.type.facility_status" :key="dict.value" :label="dict.value">{{
              dict.label }}</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item v-if="form.equipmentStatus != 1" label="设备情况说明" prop="equipmentRemark">
          <el-input v-model="form.equipmentRemark" style="width:190px" type="textarea" placeholder="请输入设备情况说明" />
        </el-form-item>

        <el-form-item label="桩位复核及图纸复核照片" class="upload-form-item">
          <div class="upload-container">
            <el-upload ref="upload" drag action="#" :auto-upload="true" list-type="picture-card"
              :on-change="onUploadChange" :on-remove="onUploadRemove" :on-exceed="onUploadExceed"
              :file-list="uploadFileList" accept="image/*" class="upload-component" :http-request="handleCustomUpload">
              <i class="el-icon-upload" />
              <div class="el-upload__text">
                将图片拖到此处，或<em>点击上传</em>
              </div>
              <div class="el-upload__tip" slot="tip">
                仅用于随单据上传的图片凭证，支持多张
              </div>
            </el-upload>
          </div>
        </el-form-item>
        <el-form-item label="次日计划" prop="nextDayPlan">
          <el-input v-model="form.nextDayPlan" style="width:190px" type="textarea" placeholder="请输入内容" />
        </el-form-item>
        <!-- <el-form-item label="上传文件" class="upload-form-item">
          <div class="upload-container">
            <el-upload ref="fileUpload" drag action="#" :auto-upload="true" list-type="text"
              :on-change="onFileUploadChange" :on-remove="onFileUploadRemove" :on-exceed="onFileUploadExceed"
              :file-list="uploadDocumentList" accept=".pdf,.doc,.docx" class="file-upload-component"
              :http-request="handleFileCustomUpload">
              <i class="el-icon-upload" />
              <div class="el-upload__text">
                将文件拖到此处，或<em>点击上传</em>
              </div>
              <div class="el-upload__tip" slot="tip">
                仅支持PDF和Word文件，支持多个文件
              </div>
            </el-upload>
          </div>
        </el-form-item> -->
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitForm">确 定</el-button>
        <el-button @click="cancel">取 消</el-button>
      </div>
    </el-dialog>

    <!-- 详情弹窗 -->
    <el-dialog :visible.sync="detailOpen" width="900px" :show-close="true" append-to-body class="daily-detail-dialog">
      <!-- <template #title>
        <span>施工日志详情</span>
      </template> -->
      <!-- 移除.daily-detail-container容器，保留其子内容 -->
      <div class="daily-detail-title">施工日志详情</div>

      <div class="daily-section-title">基本信息</div>
      <div class="daily-row-flex">
        <div class="daily-col-flex">
          <table class="daily-detail-table">
            <!-- <tr>
              <th class="left-align">主键ID</th>
              <td class="value">{{ detailForm.id }}</td>
            </tr> -->
            <tr>
              <th class="left-align">施工日期</th>
              <td class="value">{{ getDateOnly(detailForm.constructionDate) }}</td>
            </tr>
            <tr>
              <th class="left-align">桩基设备型号</th>
              <td class="value">{{ detailForm.pileEquipmentModel }}</td>
            </tr>
            <tr>
              <th class="left-align">桩基设备数量</th>
              <td class="value">{{ detailForm.pileEquipmentCount }}</td>
            </tr>
            <tr>
              <th class="left-align">工程桩数（根）</th>
              <td class="value">{{ detailForm.pileCount }}</td>
            </tr>
            <tr>
              <th class="left-align">工程量（米）</th>
              <td class="value">{{ detailForm.workLength }}</td>
            </tr>
            <tr>
              <th class="left-align">管理人员数量</th>
              <td class="value">{{ detailForm.managerCount }}</td>
            </tr>
            <tr>
              <th class="left-align">用电量</th>
              <td class="value">{{ detailForm.usePower }}</td>
            </tr>


          </table>
        </div>
        <div class="daily-col-flex">
          <table class="daily-detail-table">
            <tr>
              <th class="left-align">项目</th>
              <td class="value">{{ getProjectNameById(detailForm.projectId) }}</td>
            </tr>
            <tr>
              <th class="left-align">天气</th>
              <td class="value">{{ detailForm.weather }}</td>
            </tr>
            <tr>
              <th class="left-align">班组人员数量</th>
              <td class="value">{{ detailForm.workerCount }}</td>
            </tr>
            <tr>
              <th class="left-align">充盈系数</th>
              <td class="value">{{ detailForm.fillingCoefficient }}</td>
            </tr>
            <tr>
              <th class="left-align">用油量</th>
              <td class="value">{{ detailForm.oilConsumption }}</td>
            </tr>
            <tr>
              <th class="left-align">停工时间</th>
              <td class="value">{{ detailForm.downtime }}</td>
            </tr>

            <tr>
              <th class="left-align">其他补充说明</th>
              <td class="value">
                <div class="text-block">{{ detailForm.otherSupplement }}</div>
              </td>
            </tr>
          </table>
        </div>
      </div>

      <div class="daily-section-title">安全与设备</div>
      <table class="daily-detail-table">
        <tr>
          <th class="center-bg">
            <span class="icon">🛡️</span>安全情况
          </th>
          <td class="value">
            <dict-tag :options="dict.type.safety_status" :value="detailForm.safetyStatus" />
          </td>
        </tr>
        <tr v-if="detailForm.safetyStatus != 1">
          <th class="center-bg">
            <span class="icon">🔒</span>安全异常情况
          </th>
          <td class="value">
            <div class="text-block">{{ detailForm.safetyRemark }}</div>
          </td>
        </tr>
        <tr>
          <th class="center-bg">
            <span class="icon">🛠️</span>设备情况
          </th>
          <td class="value">
            <dict-tag :options="dict.type.facility_status" :value="detailForm.equipmentStatus" />
          </td>
        </tr>
        <tr v-if="detailForm.equipmentStatus != 1">
          <th class="center-bg">
            <span class="icon">📝</span>设备情况说明
          </th>
          <td class="value">
            <div class="text-block">{{ detailForm.equipmentRemark }}</div>
          </td>
        </tr>
      </table>


      <div class="daily-section-title" v-if="detailImageUrls.length || detailFileList.length">桩位复核及图纸复核照片</div>
      <div v-if="detailImageUrls && detailImageUrls.length > 0" class="image-display-container">
        <div v-for="(url, index) in detailImageUrls" :key="`display-${index}`" class="image-item">
          <el-image :src="url" :preview-src-list="detailImageUrls" fit="cover" class="detail-image">
            <div slot="error" class="image-slot">
              <i class="el-icon-picture-outline"></i>
            </div>
          </el-image>
        </div>
      </div>

      <div v-if="detailFileList && detailFileList.length > 0" class="daily-section-title">附件信息</div>
      <div v-if="detailFileList && detailFileList.length > 0" class="file-display-container">
        <div v-for="(file, index) in detailFileList" :key="`file-${index}`" class="file-item">
          <div class="file-info">
            <i class="el-icon-document"></i>
            <span class="file-name">{{ file.fileName }}</span>
            <div class="file-actions">
              <el-button type="primary" size="mini" icon="el-icon-download" @click="handleFileDownload(file)">
                下载
              </el-button>
              <el-button type="success" size="mini" icon="el-icon-view" @click="handleFilePreview(file)">
                预览
              </el-button>
            </div>
          </div>
        </div>
      </div>

      <div class="daily-section-title">计划与状态</div>
      <table class="daily-detail-table">
        <!-- <tr>
          <th class="center-bg">数据状态</th>
          <td class="value">正常</td>
        </tr> -->
        <tr>
          <th class="center-bg">次日计划</th>
          <td class="value">
            <div class="text-block">{{ detailForm.nextDayPlan }}</div>
          </td>
        </tr>
      </table>
      <span slot="footer" class="dialog-footer">
        <el-button @click="detailOpen = false" type="primary" plain>关闭</el-button>
      </span>
    </el-dialog>
    <el-dialog :visible.sync="previewDialogVisible" width="60vw" top="5vh" :title="getPreviewTitle()"
      @close="previewFile = null">
      <div v-if="previewFile">
        <el-image v-if="getFileType(previewFile.fileName) === 'image'" :src="previewFile.downloadUrl"
          :preview-src-list="[previewFile.downloadUrl]" fit="contain"
          style="max-width:100%;max-height:70vh;display:block;margin:auto;cursor:pointer;">
          <div slot="error" class="image-slot">
            <i class="el-icon-picture-outline"></i>
          </div>
        </el-image>
        <iframe v-else-if="['pdf', 'word', 'excel', 'ppt'].includes(getFileType(previewFile.fileName))"
          :src="previewFile.downloadUrl" style="width:100%;height:70vh;border:none;"></iframe>
        <div v-else style="text-align:center;padding:40px 0;color:#888;">
          暂不支持该类型文件的在线预览，请下载后查看。
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { listProjectDailyReport, getProjectDailyReport, delProjectDailyReport, addProjectDailyReport, updateProjectDailyReport } from "@/api/production/projectDailyReport";
import { listAllProjectContractInfo } from "@/api/production/projectContractInfo";
import { addImg } from "@/api/cost/materialLedger";
import { fileLinkTransfer, fileLinkLooking } from "@/api/production/projectFileInfo";

export default {
  name: "ProjectDailyReport",
  dicts: ['equipment_status', 'safety_status', 'facility_status', 'facility_status'],
  data() {
    return {
      // 根路径
      baseURL: process.env.VUE_APP_BASE_API,
      // 遮罩层
      loading: true,
      // 选中数组
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // 项目日报表格数据
      projectDailyReportList: [],
      // 弹出层标题
      title: "",
      // 是否显示弹出层
      open: false,
      projectOptions: [],
      // 查询参数
      queryParams: {
        projectId: null,
        pageNum: 1,
        pageSize: 10,
        projectName: null,
        constructionDate: null,
        weather: null,
        managerCount: null,
        workerCount: null,
        workAmount: null,
        fillingCoefficient: null,
        otherSupplement: null,
        safetyStatus: null,
        safetyRemark: null,
        equipmentStatus: null,
        equipmentRemark: null,
        nextDayPlan: null,
      },
      // 表单参数
      form: {},
      // 表单校验
      rules: {
        projectId: [
          { required: true, message: "项目不能为空", trigger: "blur" }
        ],
        projectName: [
          { required: true, message: "项目名称不能为空", trigger: "blur" }
        ],
        constructionDate: [
          { required: true, message: "施工日期不能为空", trigger: "blur" }
        ],
        weather: [
          { required: true, message: "天气不能为空", trigger: "blur" }
        ],
        managerCount: [
          { required: true, message: "管理人员数量不能为空", trigger: "blur" }
        ],
        workerCount: [
          { required: true, message: "班组人员数量不能为空", trigger: "blur" }
        ],
        pileEquipmentModel: [
          { required: true, message: "桩基设备型号不能为空", trigger: "blur" }
        ],
        pileEquipmentCount: [
          { required: true, message: "桩基设备数量不能为空", trigger: "blur" }
        ],
        pileCount: [
          { required: true, message: "工程桩数不能为空", trigger: "blur" }
        ],
        workLength: [
          { required: true, message: "工程量不能为空", trigger: "blur" }
        ],
        workAmount: [
          { required: true, message: "施工工程量不能为空", trigger: "blur" }
        ],
        fillingCoefficient: [
          { required: true, message: "充盈系数不能为空", trigger: "blur" }
        ],
        usePower: [
          { required: true, message: "用电量不能为空", trigger: "blur" }
        ],
        oilConsumption: [
          { required: true, message: "用油量不能为空", trigger: "blur" }
        ],
        // otherSupplement: [
        //   { required: true, message: "其他补充说明不能为空", trigger: "blur" }
        // ],
        safetyStatus: [
          { required: true, message: "安全情况不能为空", trigger: "blur" }
        ],
        safetyRemark: [
          { required: true, message: "安全异常情况说明不能为空", trigger: "blur" }
        ],
        equipmentStatus: [
          { required: true, message: "设备情况不能为空", trigger: "blur" }
        ],
        equipmentRemark: [
          { required: true, message: "设备情况说明不能为空", trigger: "blur" }
        ],
        nextDayPlan: [
          { required: true, message: "次日计划不能为空", trigger: "blur" }
        ],
      },
      detailOpen: false,
      detailForm: {},
      detailImageUrls: [],
      detailFileList: [],
      previewDialogVisible: false,
      previewFile: null,
      uploadFileList: [],
      uploadDocumentList: [],
    };
  },
  created() {
    this.fetchProjectOptions(); // 获取项目
    this.getList();
  },
  methods: {
    /** 查询项目日报列表 */
    getList() {
      this.loading = true;
      listProjectDailyReport(this.queryParams).then(response => {
        this.projectDailyReportList = response.rows;
        this.total = response.total;
        this.loading = false;
      });
    },
    // 取消按钮
    cancel() {
      this.open = false;
      this.reset();
    },
    // 表单重置
    reset() {
      this.form = {
        id: null,
        projectName: null,
        constructionDate: null,
        weather: null,
        managerCount: null,
        workerCount: null,
        workAmount: null,
        fillingCoefficient: null,
        otherSupplement: null,
        safetyStatus: '1',
        safetyRemark: null,
        equipmentStatus: '1',
        equipmentRemark: null,
        nextDayPlan: null,
        imageList: [],
      };
      this.uploadFileList = [];
      this.uploadDocumentList = [];
      this.resetForm("form");
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    // 多选框选中数据
    handleSelectionChange(selection) {
      this.ids = selection.map(item => item.id)
      this.single = selection.length !== 1
      this.multiple = !selection.length
    },
    /** 新增按钮操作 */
    handleAdd() {
      this.reset();
      this.open = true;
      this.title = "添加项目日志";
    },
    /** 修改按钮操作 */
    async handleUpdate(row) {
      this.reset();
      const id = row.id || this.ids
      const response = await getProjectDailyReport(id);
      this.form = response.data || {};
      this.form.imageList = this.normalizeImageListData(this.form.imageList);
      await this.processImageListForDisplay();
      this.open = true;
      this.title = "修改项目日志";
    },
    /** 提交按钮 */
    submitForm() {
      this.$refs["form"].validate(valid => {
        if (valid) {
          if (this.form.id != null) {
            updateProjectDailyReport(this.form).then(response => {
              this.$modal.msgSuccess("修改成功");
              this.open = false;
              this.getList();
            });
          } else {
            addProjectDailyReport(this.form).then(response => {
              this.$modal.msgSuccess("新增成功");
              this.open = false;
              this.getList();
            });
          }
        }
      });
    },
    /** 删除按钮操作 */
    handleDelete(row) {
      const ids = row.id || this.ids;
      this.$modal.confirm('是否确认删除？').then(function () {
        return delProjectDailyReport(ids);
      }).then(() => {
        this.getList();
        this.$modal.msgSuccess("删除成功");
      }).catch(() => { });
    },
    /** 导出按钮操作 */
    handleExport() {
      this.download('production/projectDailyReport/export', {
        ...this.queryParams
      }, `projectDailyReport_${new Date().getTime()}.xlsx`)
    },
    // 获取项目列表
    fetchProjectOptions() {
      listAllProjectContractInfo().then(res => {
        // console.log(1, res);
        this.projectOptions = res.data || [];
        // 默认选中第一个项目
        if (this.projectOptions.length == 1 && !this.queryParams.projectId) {
          this.queryParams.projectId = this.projectOptions[0].id;
          this.handleQuery();
        }
      });
    },
    /** 根据项目ID获取项目名称 */
    getProjectNameById(projectId) {
      // console.log(2, projectId, this.projectOptions);
      const item = this.projectOptions.find(p => p.id == projectId);
      return item ? item.projectName : projectId;
    },
    changeTime(time) {
      if (!time) return '';
      const date = new Date(time);
      if (isNaN(date.getTime())) return time;
      const pad = n => n < 10 ? '0' + n : n;
      const y = date.getFullYear();
      const m = pad(date.getMonth() + 1);
      const d = pad(date.getDate());
      const h = pad(date.getHours());
      const min = pad(date.getMinutes());
      const s = pad(date.getSeconds());
      return `${y}-${m}-${d} ${h}:${min}:${s}`;
    },
    // 只保留年月日
    getDateOnly(datetime) {
      if (!datetime) return '';
      // 兼容字符串和Date对象
      const str = typeof datetime === 'string' ? datetime : this.changeTime(datetime);
      // 匹配 yyyy-MM-dd
      const match = str.match(/^\d{4}-\d{2}-\d{2}/);
      return match ? match[0] : str;
    },
    async handleDetail(row) {
      const response = await getProjectDailyReport(row.id);
      this.detailForm = response.data || {};
      this.detailForm.imageList = this.normalizeImageListData(this.detailForm.imageList);
      await this.processDetailImageAndFiles();
      this.detailOpen = true;
    },
    // 验证工程量输入，只允许数字和小数点
    validateWorkLength(value) {
      // 移除非数字和小数点的字符
      const newValue = value.replace(/[^\d.]/g, '');

      // 确保只有一个小数点
      const parts = newValue.split('.');
      if (parts.length > 2) {
        this.form.workLength = parts[0] + '.' + parts.slice(1).join('');
      } else {
        this.form.workLength = newValue;
      }

      // 限制小数点后最多2位
      if (newValue.includes('.')) {
        const decimalPart = newValue.split('.')[1];
        if (decimalPart && decimalPart.length > 2) {
          this.form.workLength = newValue.substring(0, newValue.indexOf('.') + 3);
        }
      }
    },
    // 格式化工程量，失去焦点时处理
    formatWorkLength() {
      if (this.form.workLength) {
        // 转换为数字并保留2位小数
        const num = parseFloat(this.form.workLength);
        if (!isNaN(num)) {
          this.form.workLength = num.toFixed(2);
        }
      }
    },
    // 验证正整数输入，只允许数字
    validatePositiveInteger(fieldName) {
      // 移除非数字字符
      const newValue = this.form[fieldName].replace(/\D/g, '');
      this.form[fieldName] = newValue;
    },
    // 格式化正整数，失去焦点时处理
    formatPositiveInteger(fieldName) {
      if (this.form[fieldName]) {
        // 转换为整数
        const num = parseInt(this.form[fieldName]);
        if (!isNaN(num)) {
          this.form[fieldName] = num.toString();
        }
      }
    },
    // 验证正数输入，只允许数字和小数点
    validatePositiveNumber(fieldName) {
      // 移除非数字和小数点的字符
      const newValue = this.form[fieldName].replace(/[^\d.]/g, '');

      // 确保只有一个小数点
      const parts = newValue.split('.');
      if (parts.length > 2) {
        this.form[fieldName] = parts[0] + '.' + parts.slice(1).join('');
      } else {
        this.form[fieldName] = newValue;
      }

      // 限制小数点后最多2位
      if (newValue.includes('.')) {
        const decimalPart = newValue.split('.')[1];
        if (decimalPart && decimalPart.length > 2) {
          this.form[fieldName] = newValue.substring(0, newValue.indexOf('.') + 3);
        }
      }
    },
    // 格式化正数，失去焦点时处理
    formatPositiveNumber(fieldName) {
      if (this.form[fieldName]) {
        // 转换为数字并保留2位小数
        const num = parseFloat(this.form[fieldName]);
        if (!isNaN(num)) {
          this.form[fieldName] = num.toFixed(2);
        }
      }
    },
    onUploadChange(file, fileList) {
      this.uploadFileList = fileList;
    },
    async handleCustomUpload(param) {
      const { file } = param || {};
      if (!file) {
        param?.onError?.(new Error("无可上传文件"));
        return;
      }
      try {
        const { msg: filePath } = await addImg(file);
        if (!filePath) throw new Error("未获取到文件路径");
        const { data: { url } } = await fileLinkTransfer(filePath);
        if (!url) throw new Error("未获取到可访问的图片链接");
        const fileItem = {
          name: file.name || "image.jpg",
          url,
          uid: file.uid?.toString() || Date.now().toString(),
          originalPath: filePath,
        };
        this.uploadFileList = [...this.uploadFileList, fileItem];
        if (!Array.isArray(this.form.imageList)) this.form.imageList = [];
        this.form.imageList.push(filePath);
        param?.onSuccess?.({ url });
      } catch (err) {
        this.$message.error("图片上传失败");
        param?.onError?.(err);
      }
    },
    async onUploadRemove(file, fileList) {
      const { url } = file || {};
      if (url) {
        const fileItem = this.uploadFileList.find(item => item.url === url);
        if (fileItem?.originalPath && Array.isArray(this.form.imageList)) {
          const index = this.form.imageList.indexOf(fileItem.originalPath);
          if (index > -1) {
            this.form.imageList.splice(index, 1);
          }
        }
      }
      this.uploadFileList = fileList;
    },
    onUploadExceed(files, fileList) {
      this.$message.warning(`当前限制选择 ${fileList.length} 张图片，已选择 ${files.length} 张`);
    },
    onFileUploadChange(file, fileList) {
      this.uploadDocumentList = fileList;
    },
    async handleFileCustomUpload(param) {
      const { file } = param || {};
      if (!file) {
        param?.onError?.(new Error("无可上传文件"));
        return;
      }
      const allowedTypes = ['.pdf', '.doc', '.docx'];
      const fileExtension = '.' + file.name.split('.').pop().toLowerCase();
      if (!allowedTypes.includes(fileExtension)) {
        this.$message.error("只支持PDF和Word文件");
        param?.onError?.(new Error("文件类型不支持"));
        return;
      }
      try {
        const { msg: filePath } = await addImg(file);
        if (!filePath) throw new Error("未获取到文件路径");
        const { data: { url } } = await fileLinkTransfer(filePath);
        if (!url) throw new Error("未获取到可访问的文件链接");
        const fileItem = {
          name: file.name || "document.pdf",
          url,
          uid: file.uid?.toString() || Date.now().toString(),
          originalPath: filePath,
        };
        this.uploadDocumentList = [...this.uploadDocumentList, fileItem];
        if (!Array.isArray(this.form.imageList)) this.form.imageList = [];
        this.form.imageList.push(filePath);
        param?.onSuccess?.({ url });
      } catch (err) {
        this.$message.error("文件上传失败");
        param?.onError?.(err);
      }
    },
    async onFileUploadRemove(file, fileList) {
      const { url } = file || {};
      if (url) {
        const fileItem = this.uploadDocumentList.find(item => item.url === url);
        if (fileItem?.originalPath && Array.isArray(this.form.imageList)) {
          const index = this.form.imageList.indexOf(fileItem.originalPath);
          if (index > -1) {
            this.form.imageList.splice(index, 1);
          }
        }
      }
      this.uploadDocumentList = fileList;
    },
    onFileUploadExceed(files, fileList) {
      this.$message.warning(`当前限制选择 ${fileList.length} 个文件，已选择 ${files.length} 个`);
    },
    getFileType(fileName) {
      if (!fileName) return 'unknown';
      const extension = fileName.split('.').pop().toLowerCase();
      const imageTypes = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp', 'svg'];
      const pdfTypes = ['pdf'];
      const wordTypes = ['doc', 'docx'];
      const excelTypes = ['xls', 'xlsx'];
      const pptTypes = ['ppt', 'pptx'];
      if (imageTypes.includes(extension)) return 'image';
      if (pdfTypes.includes(extension)) return 'pdf';
      if (wordTypes.includes(extension)) return 'word';
      if (excelTypes.includes(extension)) return 'excel';
      if (pptTypes.includes(extension)) return 'ppt';
      return 'unknown';
    },
    isImageFile(fileType) {
      return fileType === 'image';
    },
    getFileNameFromUrl(url) {
      if (!url) return 'unknown';
      const parts = url.split('/');
      return parts[parts.length - 1] || 'unknown';
    },
    async getDisplayImageUrl(url) {
      if (!url) return "";
      try {
        const { data: { url: accessibleUrl } } = await fileLinkTransfer(url);
        return accessibleUrl || url;
      } catch (error) {
        console.error("getDisplayImageUrl - 转换失败:", error);
        return url;
      }
    },
    async processImageListForDisplay() {
      if (!this.form.imageList?.length) {
        this.uploadFileList = [];
        this.uploadDocumentList = [];
        return;
      }
      this.uploadFileList = [];
      this.uploadDocumentList = [];
      for (let i = 0; i < this.form.imageList.length; i++) {
        const url = this.form.imageList[i];
        try {
          const displayUrl = await this.getDisplayImageUrl(url);
          const fileName = this.getFileNameFromUrl(url);
          const fileType = this.getFileType(fileName);
          if (this.isImageFile(fileType)) {
            this.uploadFileList.push({
              name: fileName || `image_${i + 1}.jpg`,
              url: displayUrl,
              uid: `existing_image_${i}`,
              originalPath: url,
            });
          } else {
            this.uploadDocumentList.push({
              name: fileName || `document_${i + 1}`,
              url: displayUrl,
              uid: `existing_file_${i}`,
              originalPath: url,
            });
          }
        } catch (error) {
          console.error("processImageListForDisplay - 转换失败:", error);
          const fileName = this.getFileNameFromUrl(url);
          const fileType = this.getFileType(fileName);
          if (this.isImageFile(fileType)) {
            this.uploadFileList.push({
              name: fileName || `image_${i + 1}.jpg`,
              url,
              uid: `existing_image_${i}`,
              originalPath: url,
            });
          } else {
            this.uploadDocumentList.push({
              name: fileName || `document_${i + 1}`,
              url,
              uid: `existing_file_${i}`,
              originalPath: url,
            });
          }
        }
      }
    },
    async processDetailImageAndFiles() {
      if (!this.detailForm.imageList?.length) {
        this.detailImageUrls = [];
        this.detailFileList = [];
        return;
      }
      this.detailImageUrls = [];
      this.detailFileList = [];
      for (let i = 0; i < this.detailForm.imageList.length; i++) {
        const url = this.detailForm.imageList[i];
        try {
          const displayUrl = await this.getDisplayImageUrl(url);
          const fileName = this.getFileNameFromUrl(url);
          const fileType = this.getFileType(fileName);
          if (this.isImageFile(fileType)) {
            this.detailImageUrls.push(displayUrl);
          } else {
            this.detailFileList.push({
              fileName,
              downloadUrl: url,
              displayUrl,
              fileType,
            });
          }
        } catch (error) {
          console.error("processDetailImageAndFiles - 转换失败:", error);
        }
      }
    },
    async handleFileDownload(file) {
      if (!file.downloadUrl) {
        this.$message.error("无效的下载链接");
        return;
      }
      try {
        const res = await fileLinkTransfer(file.downloadUrl);
        const newUrl = res.data.url;
        if (!newUrl) {
          this.$message.error("获取下载链接失败");
          return;
        }
        const a = document.createElement("a");
        a.href = newUrl;
        a.download = file.fileName || "";
        a.target = "_blank";
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
      } catch (e) {
        this.$message.error("下载失败");
      }
    },
    async handleFilePreview(file) {
      if (!file.downloadUrl) {
        this.$message.error("无效的预览链接");
        return;
      }
      try {
        let newUrl = '';
        const fileType = this.getFileType(file.fileName);
        if (fileType === 'image') {
          const res = await fileLinkTransfer(file.downloadUrl);
          newUrl = res.data.url;
        } else if (['pdf', 'word', 'excel', 'ppt'].includes(fileType)) {
          const res = await fileLinkLooking(file.downloadUrl);
          newUrl = res.data.url;
        } else {
          newUrl = file.downloadUrl;
        }
        if (!newUrl) {
          this.$message.error("获取预览链接失败");
          return;
        }
        this.previewFile = { ...file, downloadUrl: newUrl };
        this.previewDialogVisible = true;
      } catch (e) {
        this.$message.error("预览失败");
      }
    },
    getPreviewTitle() {
      if (this.previewFile?.fileName) {
        return this.previewFile.fileName;
      }
      return "文件预览";
    },
    normalizeImageListData(imageList) {
      if (!imageList) return [];
      if (Array.isArray(imageList)) {
        return imageList.filter(item => !!item);
      }
      if (typeof imageList === 'string') {
        let parsed = [];
        try {
          const temp = JSON.parse(imageList);
          if (Array.isArray(temp)) {
            parsed = temp;
          }
        } catch (error) {
          parsed = imageList.split(',').map(item => item.trim()).filter(item => !!item);
        }
        return parsed;
      }
      return [];
    },
  }
};
</script>

<style scoped>
.daily-detail-dialog .el-dialog__body {
  background: #f4f6fb;
  padding: 0;
}

.daily-detail-container {
  max-width: 900px;
  margin: 40px auto;
  background: #fff;
  border-radius: 12px;
  box-shadow: 0 4px 24px rgba(0, 0, 0, 0.10);
  padding: 36px 44px 32px 44px;
}

.daily-detail-title {
  font-size: 28px;
  font-weight: bold;
  color: #2d3a4b;
  margin-bottom: 36px;
  text-align: center;
  letter-spacing: 2px;
}

.daily-section-title {
  font-size: 18px;
  color: #4a90e2;
  font-weight: bold;
  margin: 32px 0 16px 0;
  border-left: 4px solid #4a90e2;
  padding-left: 12px;
  letter-spacing: 1px;
}

.daily-row-flex {
  display: flex;
  gap: 32px;
  margin-bottom: 12px;
}

.daily-col-flex {
  flex: 1;
}

.daily-detail-table {
  width: 100%;
  border-collapse: separate;
  border-spacing: 0;
  background: none;
}

.daily-detail-table th,
.daily-detail-table td {
  padding: 10px 8px;
  font-size: 16px;
  border-bottom: 1px solid #f0f0f0;
}

.daily-detail-table th {
  width: 120px;
  color: #6b7a90;
  background: none;
  font-weight: normal;
  text-align: right;
  vertical-align: top;
  padding-right: 12px;
}

.daily-detail-table td.value {
  color: #222;
  text-align: left;
  font-weight: 500;
}

.daily-detail-table tr:last-child td,
.daily-detail-table tr:last-child th {
  border-bottom: none;
}

.text-block {
  white-space: pre-wrap;
  border-radius: 4px;
  padding: 10px 12px;
  min-height: 48px;
  border: 1px solid #e3e6ed;
  background: #fff;
  color: #444;
  font-size: 15px;
  margin: 0;
}

.icon {
  display: inline-block;
  width: 18px;
  height: 18px;
  vertical-align: middle;
  margin-right: 6px;
  opacity: 0.7;
}

.daily-detail-table th.left-align {
  text-align: center;
  padding-left: 0;
  padding-right: 0;
  background: #f7fafd;
}

.daily-detail-table th.center-bg {
  text-align: center;
  vertical-align: middle;
  background: #f7fafd;
}

@media (max-width: 900px) {
  .daily-detail-container {
    padding: 12px 2vw;
  }

  .daily-row-flex {
    flex-direction: column;
    gap: 0;
  }
}

@media (max-width: 600px) {
  .daily-detail-container {
    padding: 6px 0;
  }

  .daily-detail-title {
    font-size: 20px;
  }

  .daily-section-title {
    font-size: 15px;
    padding-left: 8px;
  }

  .daily-detail-table th,
  .daily-detail-table td {
    font-size: 13px;
    padding: 7px 4px;
  }

  .text-block {
    font-size: 13px;
    padding: 7px 7px;
  }
}

.upload-container {
  width: 100%;
  overflow: hidden;
  margin-bottom: 10px;
}

.upload-component {
  width: 100%;
}

.upload-form-item {
  margin-bottom: 20px;
}

.upload-form-item .el-form-item__content {
  margin-bottom: 10px;
}

::v-deep .el-form--inline .upload-form-item {
  width: 100%;
  display: flex;
  align-items: flex-start;
}

::v-deep .el-form--inline .upload-form-item .el-form-item__content {
  flex: 1;
  width: auto;
}

::v-deep .upload-component .el-upload--picture-card {
  width: 120px;
  height: 120px;
  line-height: 118px;
}

::v-deep .upload-component .el-upload-list--picture-card .el-upload-list__item {
  width: 120px;
  height: 120px;
}

::v-deep .upload-component .el-upload-dragger {
  width: 100%;
  height: 120px;
}

::v-deep .upload-component .el-upload-list--picture-card {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 8px;
  margin-bottom: 10px;
}

::v-deep .upload-component .el-upload-list--picture-card .el-upload-list__item {
  margin: 0;
}

::v-deep .el-dialog__body .upload-container {
  max-width: 100%;
  box-sizing: border-box;
}

::v-deep .upload-component .el-upload-dragger {
  border: 2px dashed #d9d9d9;
  border-radius: 6px;
}

::v-deep .upload-component .el-upload-dragger:hover {
  border-color: #409eff;
}

.file-upload-component {
  width: 100%;
}

.file-upload-component .el-upload-dragger {
  width: 100%;
  height: 120px;
  border: 2px dashed #d9d9d9;
  border-radius: 6px;
  background: #fafafa;
  text-align: center;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
}

.file-upload-component .el-upload-dragger:hover {
  border-color: #409eff;
}

.file-upload-component .el-upload__text {
  color: #606266;
  font-size: 14px;
  text-align: center;
  margin-top: 8px;
}

.file-upload-component .el-upload__text em {
  color: #409eff;
  font-style: normal;
}

.file-upload-component .el-upload__tip {
  font-size: 12px;
  color: #909399;
  margin-top: 8px;
  text-align: center;
}

.file-upload-component .el-upload-list--text {
  margin-top: 8px;
}

.file-upload-component .el-upload-list--text .el-upload-list__item {
  background-color: #f5f7fa;
  border: 1px solid #e4e7ed;
  border-radius: 4px;
  padding: 8px 12px;
  margin-bottom: 4px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.file-upload-component .el-upload-list--text .el-upload-list__item-name {
  color: #606266;
  font-size: 14px;
  flex: 1;
  margin-right: 8px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-upload-component .el-upload-list--text .el-upload-list__item-status-label {
  color: #67c23a;
  font-size: 12px;
}

.file-upload-component .el-upload-list--text .el-upload-list__item-delete {
  color: #f56c6c;
  cursor: pointer;
  font-size: 16px;
}

.image-display-container {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin: 16px 0;
}

.image-item {
  width: 120px;
  height: 120px;
  border-radius: 6px;
  overflow: hidden;
  border: 1px solid #e4e7ed;
}

.detail-image {
  width: 100%;
  height: 100%;
}

.image-slot {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  background: #f5f7fa;
  color: #909399;
  font-size: 20px;
}

.file-display-container {
  margin: 16px 0;
}

.file-item {
  margin-bottom: 12px;
  padding: 12px;
  background: #f8f9fa;
  border: 1px solid #e9ecef;
  border-radius: 6px;
  transition: all 0.2s;
}

.file-item:hover {
  background: #e9ecef;
  border-color: #409eff;
}

.file-info {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.file-info i {
  color: #409eff;
  font-size: 18px;
  margin-right: 8px;
}

.file-name {
  flex: 1;
  color: #333;
  font-size: 14px;
  margin-right: 12px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-actions {
  display: flex;
  gap: 8px;
}

.file-actions .el-button {
  padding: 4px 8px;
  font-size: 12px;
}
</style>
